package com.swf.seed.jolt;

import bea.jolt.pool.SessionPool;
import bea.jolt.pool.DataSet;
import bea.jolt.JoltRemoteService;
import bea.jolt.JoltMessage;

/**
 * <p>Title: Jolt调用者</p>
 * <p>Description: 使用该类调用Tuxedo的服务,并得到返回结果。示例代码如下：
 * <P>
* <code>IJoltData data = JoltCaller.getJoltData( "serviceName" );<br/>
*       ... ... // 根据协议赋值<br/>
*       JoltCaller caller = new JoltCaller();<br/>
*       data = caller.call( data );<br/>
*       ... ... // 处理返回数据<br/>
*       caller.finish(); // 完成此次调用<br/>
*       </code></P>
 * </p>
 * <p>Copyright: Copyright (c) 2009</p>
 * <p>Company: Beijing Watchdata CO,.Ltd</p>
 * @author da.wang
 * @version 1.0
 */
public class JoltCaller {

    private IJoltData data = null;

    public JoltCaller() {
    }

    /**
     * 调用Tuxedo服务
     * @param data IJoltData 调用Tuxedo服务的数据
     * @throws WDJoltException 如果读取配置文件出错;调用服务出错（超时出错）;封装数据出错;
     * @return IJoltData 服务返回的结果
     */
    public IJoltData call( IJoltData data )
        throws WDJoltException {
        // 获取默认连接池的
        return call( data, null );
    }

    /**
     * 调用Tuxedo服务
     * @param data IJoltData 调用Tuxedo服务的数据
     * @param sessionName String 使用池时,会话池的名字
     * @throws WDJoltException 如果读取配置文件出错;调用服务出错（超时出错）;封装数据出错;
     * @return IJoltData 服务返回的结果
     */
    public IJoltData call( IJoltData data, String sessionName )
        throws WDJoltException {
        JoltConfig cfg = JoltConfig.getInstance();
        // 保存调用对象

        IJoltData rlt = null;
        // 检查是否是长连接
        if ( cfg.isPoolEnable() ) {
            // 长连接
            // 得到SessionPool
            SessionPool pool = null;
            if ( sessionName == null || sessionName.equals( "" ) ) {
                pool = JoltPoolManager.getPool();
            }
            else {
                pool = JoltPoolManager.getPool( sessionName );
            }

            // 通过SessionPool调用服务,不使用事务
            DataSet ds = null;
            if ( pool == null ) {
                throw new WDJoltException( "*******Can not get SessionPool." );
            }
            ds = pool.call( data.getServiceName(), (DataSet)data.getData(), null );
            if ( ds.size() == 0 ) {
                throw new WDJoltException( "*******Tuxedo servece return null. Maybe receive timeout!" );
            }
            // 封装返回结果
            rlt = new PoolledJoltData();
            rlt.setData( ds );
        }
        else {
            // 短连接
            JoltRemoteService service = null;
            try {
                // 得到RemoteService
                service = ( JoltRemoteService )data.getData();

                // 调用服务
                service.call( null );
            }
            catch( RuntimeException ex ) {
                throw new WDJoltException( "*******Exception occured when service calling:" + ex.getMessage(), ex );
            }

            // 封装返回结果
            JoltMessage msg = service.getOutputs();
            String s = msg.getStringDef( "STRING", "" );
            rlt = new BasicCallResult( msg );
        }
        return rlt;
    }

    /**
     * 根据当前的配置,生成适当的Jolt调用数据
     * @return IJoltData Jolt调用数据
     */
    public IJoltData getJoltData( String serviceName )
        throws WDJoltException {
        return getJoltData( serviceName, null );
    }

    /**
     * 根据当前的配置,生成适当的Jolt调用数据。
     * @param serviceName String 服务名
     * @param cfg BasicJoltConfig 短连接配置，这个参数主要是对短连接调用时生效，长连接时不会使用该配置参数
     * @return IJoltData 短连接调用数据
     */
    public IJoltData getJoltData( String serviceName, BasicJoltConfig cfg )
        throws WDJoltException {
        if ( serviceName == null || serviceName.equals( "" ) ) {
            throw new IllegalArgumentException( "*******ServiceName is null!" );
        }
        IJoltData data = null;
        JoltConfig joltCfg = JoltConfig.getInstance();
        boolean isPool = joltCfg.isPoolEnable();
        if ( isPool ) {
            data = new PoolledJoltData();
        }
        else {
            if ( cfg == null ) {
                // 没有短连接配置时,使用默认配置
                data = new BasicJoltData( joltCfg.getBasicConfig(), serviceName.trim() );
            }
            else {
                // 有短连接配置时,使用特定的短连接配置,这样就可以使每一个短连接调用都可以单独配置
                data = new BasicJoltData( cfg, serviceName.trim() );
            }
        }
        data.setServiceName( serviceName.trim() );
        return data;
    }

    /**
     * 完成服务调用，主要是对短连接调用生效，长连接不会做任何操作。
     */
    public void finish() {
        data.destroy();
    }

}
